package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"

	"gitee.com/liumou_site/ssh-guardian/model"
)

// main 函数是程序的入口点，负责解析命令行参数并启动 SSH 检测和备份任务。
// 该函数定义了四个命令行参数：
//   - source: SSH 源路径，默认值为 "/usr/local/openssh"。
//   - backup: SSH 备份路径，默认值为 "/usr/local/.ssh"。
//   - port: SSH 端口，默认值为 22。
//   - sec: 检测间隔时间（秒），默认值为 180。
//
// 函数会持续运行，定期执行 SSH 检测和备份任务，并在每次任务执行后休眠指定的时间间隔。
func main() {
	// 检查配置文件语言设置，优先使用配置文件中的语言
	configLang := model.GetConfigLanguage()
	isChina := configLang == "zh"

	// 定义命令行参数变量（先定义变量，帮助信息在参数解析前动态设置）
	var sourcePath, backupPath *string
	var port, sec *int
	var init, debug, ver, conf *bool
	var lang *string

	// 定义帮助信息函数，根据当前语言设置返回对应的帮助文本
	getHelp := func(chinese, english string) string {
		if isChina {
			return chinese
		}
		return english
	}

	// 定义命令行参数并设置默认值（帮助信息根据语言动态设置）
	sourcePath = flag.String("source", "", getHelp("SSH源路径", "SSH source path"))
	backupPath = flag.String("backup", "/usr/local/.ssh", getHelp("SSH备份路径", "SSH backup path"))
	port = flag.Int("port", 22, getHelp("SSH端口", "SSH port"))
	sec = flag.Int("sec", 180, getHelp("检测间隔时间（秒）", "Detection interval (seconds)"))
	init = flag.Bool("init", false, getHelp("初始化配置", "Initialize configuration"))
	debug = flag.Bool("debug", false, getHelp("调试模式", "Debug mode"))
	ver = flag.Bool("ver", false, getHelp("版本信息", "Version information"))
	lang = flag.String("lang", "en", getHelp("语言设置 (zh/en)", "Language setting (zh/en)"))
	conf = flag.Bool("conf", true, getHelp("使用配置文件参数", "Use configuration file parameters"))

	// 解析命令行参数
	flag.Parse()

	// 检查sourcePath参数：默认为空，如果传入了值则检查路径和目录结构
	if *sourcePath == "" {
		*sourcePath = "/usr/local/openssh"
	} else {
		// 验证路径存在性和目录结构是否符合编译安装结果
		if !validateCompiledSSHPath(*sourcePath) {
			fmt.Printf("错误：指定的路径 '%s' 不存在或不符合编译安装的目录结构\n", *sourcePath)
			fmt.Printf("Error: Specified path '%s' does not exist or does not match compiled installation directory structure\n", *sourcePath)
			os.Exit(1)
		}
	}

	// 验证语言参数
	if *lang != "zh" && *lang != "en" {
		fmt.Printf("错误：语言参数必须是 'zh' 或 'en'\n")
		fmt.Printf("Error: Language parameter must be 'zh' or 'en'\n")
		flag.Usage()
		os.Exit(1)
	}

	// 如果命令行明确指定了语言参数，则优先使用命令行设置
	switch *lang {
	case "zh":
		isChina = true
	case "en":
		isChina = false
	}

	// 初始化全局语言管理器
	model.InitLanguageManager(isChina)

	// 获取语言管理器
	langManager := model.GetLanguageManager()

	if *ver {
		langManager.Info("版本:", "version:", model.Version())
		return
	}

	langManager.Info("SSH源路径: "+*sourcePath, "SSH from path: "+*sourcePath)
	langManager.Info("SSH备份路径: "+*backupPath, "SSH Backup Path: "+*backupPath)
	if *conf {
		langManager.Info("使用配置文件参数", "Use configuration file parameters")
	} else {
		langManager.Info("使用命令参数", "Use command parameters")
	}

	// 检查当前环境是否为Linux，如果不是，可能会影响后续操作。
	model.CheckLinuxEnvironment()
	// 检查当前进程是否具有root权限，如果不是，可能会影响后续操作。
	model.CheckRootPermission()
	// 检查当前系统是否支持systemd，如果不支持则记录错误并返回。
	model.CheckSystemd()

	// 智能服务注册逻辑：统一判断是否需要进入注册流程
	// 如果传入-init参数或者服务未注册，则进入注册流程
	// 否则跳过注册流程
	needRegistration := *init || !model.IsServiceRegistered()

	if needRegistration {
		if *init {
			langManager.Info("检测到-init参数，进入注册流程", "Detected -init parameter, entering registration process")
		} else {
			langManager.Info("检测到SSH Guardian服务未注册，自动进入注册流程", "SSH Guardian service not registered, automatically entering registration process")
		}
		// 初始化配置,执行完成后退出程序,退出代码为0
		model.InitConfig(*sourcePath, *backupPath, *port, *sec, isChina, *debug)
	} else {
		langManager.Info("SSH Guardian服务已注册且未传入-init参数，跳过注册流程", "SSH Guardian service already registered and no -init parameter provided, skipping registration process")
	}

	model.Start(*sourcePath, *backupPath, *port, *sec, *debug, isChina, *conf, *init)
}

// validateCompiledSSHPath 验证指定路径是否为编译安装的SSH目录结构
// 检查路径是否存在以及是否包含编译安装的典型目录结构
func validateCompiledSSHPath(path string) bool {
	// 首先检查路径是否存在
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}

	// 编译安装SSH的典型目录结构检查
	requiredDirs := []string{
		"bin",
		"sbin",
		"libexec",
		"share",
	}

	requiredBinaries := []string{
		"bin/ssh",
		"bin/ssh-keygen",
		"sbin/sshd",
	}

	// 检查必需的目录是否存在
	for _, dir := range requiredDirs {
		dirPath := filepath.Join(path, dir)
		if _, err := os.Stat(dirPath); os.IsNotExist(err) {
			return false
		}
	}

	// 检查必需的二进制文件是否存在
	for _, binary := range requiredBinaries {
		binaryPath := filepath.Join(path, binary)
		if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
			return false
		}
	}

	return true
}
